package com.company.common.util;

import org.apache.commons.collections.CollectionUtils;

import java.util.*;

/**
 * 字段补充者
 *
 * @param <K> 根据字段ID类型
 * @param <M> 填充字段ID类型的中间值，里面可能包含了真正要设置进T的值
 * @param <I> 需要补充字段的对象类型
 */
public abstract class DirectFieldFiller<K, M, I> {

    // 定义如何从obj里面获取补充字段的根据
    protected abstract K whichIdNeed(I item);

    protected abstract K getIdFromValue(M mid);

    // 定义如何从DB里批量加载对象
    protected abstract List<M> loadFromDB(List<K> ids);

    // 将对应的值塞到待填充字段的对象里
    protected abstract void fillField(I item, M mid);

    public List<M> fill(List<I> datas) {
        List<M> values = null;

        // 遍历所有对象
        if (CollectionUtils.isNotEmpty(datas)) {

            Set<K> keySet = new LinkedHashSet<>();
            // 收集所有的KEY值
            for (I data : datas) {
                K key = whichIdNeed(data);
                if (key != null) {
                    keySet.add(key);
                }
            }

            // 转成list
            List<K> keys = new ArrayList<>(keySet);
            if (CollectionUtils.isNotEmpty(keys)) {

                // 根据KEY值查出所有值，放进map备用
                values = loadFromDB(keys);
                Map<K, M> kvMap = new HashMap<>();
                if (CollectionUtils.isNotEmpty(values)) {
                    for (M v : values) {
                        K key = getIdFromValue(v);
                        kvMap.put(key, v);
                    }
                }

                // 遍历值设置到data里面去
                for (I obj : datas) {
                    K key = whichIdNeed(obj);
                    M v = kvMap.get(key);
                    if (v != null) {
                        fillField(obj, v);
                    }
                }

            }
        }

        return values;
    }

}
